//! 属性（Attributes）
//!
//! 属性是应用于 crate、模块、函数、结构体等的元数据。
//! 它们以 `#[]` 的形式出现，可以影响编译器的行为或者提供额外的信息。

/// 1. 条件编译属性
///
/// `cfg` 属性用于条件编译，允许根据编译目标或特性开关来包含或排除代码。
#[cfg(target_os = "linux")]
fn linux_only_function() {
    println!("这段代码只在 Linux 系统上编译");
}

#[cfg(target_os = "windows")]
fn windows_only_function() {
    println!("这段代码只在 Windows 系统上编译");
}

/// 根据特性开关编译不同代码
#[cfg(feature = "enable_debug")]
fn debug_function() {
    println!("调试功能已启用");
}

#[cfg(not(feature = "enable_debug"))]
fn debug_function() {
    println!("调试功能未启用");
}

/// 2. 测试相关属性
///
/// `test` 属性标记函数为测试函数
/// `should_panic` 属性期望测试函数会 panic
#[cfg(test)]
mod test_attributes {
    /// 基本测试函数
    #[test]
    fn basic_test() {
        assert_eq!(2 + 2, 4);
    }

    /// 期望 panic 的测试
    #[test]
    #[should_panic]
    fn panic_test() {
        panic!("这个测试应该 panic");
    }

    /// 带有预期 panic 信息的测试
    #[test]
    #[should_panic(expected = "除数不能为零")]
    fn panic_with_message_test() {
        panic!("除数不能为零");
    }

    /// 忽略的测试（默认不会运行）
    #[test]
    #[ignore]
    fn ignored_test() {
        // 这个测试需要很长时间来运行
        println!("这是一个被忽略的测试");
    }
}

/// 3. 代码生成相关属性
///
/// `derive` 属性自动生成特定 trait 的实现
#[derive(Debug, Clone, PartialEq)]
struct Person {
    name: String,
    age: u32,
}

/// `allow` 属性用于禁止特定的编译警告
#[allow(dead_code)]
fn unused_function() {
    // 这个函数未被使用，但不会产生警告
}

/// `warn` 属性用于启用特定警告
#[warn(missing_docs)]
mod module_with_warn {
    pub fn public_function() {
        // 这个函数缺少文档注释，会产生警告
    }
}

/// `deny` 属性将特定 lint 转换为错误
#[deny(unused_variables)]
fn deny_unused_variables() {
    let _x = 42; // 使用下划线前缀避免未使用变量警告
}

/// 4. 文档相关属性
///
/// `doc` 属性用于控制文档生成
#[doc(hidden)]
fn hidden_function() {
    // 这个函数在生成的文档中会被隐藏
}

/// 这个函数有一个文档示例
///
/// ```
/// use binary_demo::basic::attributes::documented_function;
/// let result = documented_function(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn documented_function(a: i32, b: i32) -> i32 {
    a + b
}

/// 5. 优化相关属性
///
/// `inline` 属性建议编译器内联函数调用
#[inline]
fn inline_function(x: i32) -> i32 {
    x * 2
}

/// `inline(always)` 属性强制编译器内联函数
#[inline(always)]
fn always_inline_function(x: i32) -> i32 {
    x * 3
}

/// `cold` 属性标记很少执行的函数（如错误处理）
#[cold]
fn error_function() {
    eprintln!("发生了一个错误");
}

/// 6. 外部函数接口相关属性
///
/// `no_mangle` 属性防止函数名被破坏
#[unsafe(no_mangle)]
pub extern "C" fn exported_function() -> i32 {
    42
}

/// 主演示函数
pub fn demonstrate_attributes() {
    println!("\n=== 属性（Attributes）示例 ===");

    // 调用条件编译函数
    #[cfg(target_os = "windows")]
    windows_only_function();

    #[cfg(target_os = "linux")]
    linux_only_function();

    // 调用调试函数
    debug_function();

    // 演示 derive 属性
    let person = Person { name: "张三".to_string(), age: 30 };
    println!("使用 derive(Debug) 的结构体: {person:?}");

    let cloned_person = person.clone();
    println!("使用 derive(Clone) 克隆的结构体: {cloned_person:?}");

    println!("使用 derive(PartialEq) 比较结构体: {}", person == cloned_person);

    // 演示 inline 函数
    println!("inline_function(5) = {}", inline_function(5));
    println!("always_inline_function(5) = {}", always_inline_function(5));

    // 演示外部函数
    println!("exported_function() = {}", exported_function());
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_documented_function() {
        assert_eq!(documented_function(2, 3), 5);
        assert_eq!(documented_function(-1, 1), 0);
    }

    #[test]
    fn test_person_derive() {
        let person1 = Person { name: "李四".to_string(), age: 25 };

        let person2 = person1.clone();

        // 测试 Clone 和 PartialEq
        assert_eq!(person1, person2);
    }

    #[test]
    #[should_panic(expected = "这个测试应该 panic")]
    fn test_should_panic() {
        panic!("这个测试应该 panic");
    }
}
